// G4提供的头文件
#include "G4Box.hh"                 // G4的长方体几何体
#include "G4Orb.hh"                 // G4的球形几何体
#include "G4Tubs.hh"                // G4的圆柱体
#include "G4LogicalVolume.hh"       // G4的逻辑体
#include "G4PVPlacement.hh"         // G4的物理实体摆放器
#include "G4SystemOfUnits.hh"       // G4系统单位制
#include "G4NistManager.hh"         // G4材料查找表
#include "G4Material.hh"            // G4材料
#include "G4VisAttributes.hh"       // G4逻辑体外观管理器
#include "G4Color.hh"               // G4的颜色
#include "G4RotationMatrix.hh"      // G4旋转矩阵
#include "G4SDManager.hh"           // SD管理器

#include "G4FieldManager.hh"        // G4磁场管理类
#include "G4UniformMagField.hh"     // G4预置磁场类
// 用户编写的头文件
#include "G4ImproveDetectorConstruction.hh"
#include "G4ImproveHit.hh"
#include "G4ImproveSD.hh"

// G4物理建模函数
G4VPhysicalVolume * G4ImproveDetectorConstruction::Construct(){

    // 创建材料查找表
    auto nistManager = G4NistManager::Instance();

    // 检查边界冲突的变量控制
    G4bool checkOverlaps = true;

    /***********************创建磁场**************************************/
    G4ThreeVector fieldValue(0.0, 0.0, 1*tesla);                        // 定义一个磁场向量
    G4UniformMagField * magField = new G4UniformMagField(fieldValue);   // 定义一个均匀磁场
    G4FieldManager * fieldManager = new G4FieldManager(magField);       // 将磁场注册到磁场管理类

    /***********************创建G4 World**********************************/
    // 创建World几何体
    auto * solid_world = new G4Box("world",
                                    0.2*m,
                                    0.2*m,
                                    0.2*m);
    // 创建World逻辑体
    auto * logic_world = new G4LogicalVolume(solid_world,           
                                             nistManager->FindOrBuildMaterial("G4_AIR"),
                                             "world");
    // 创建world物理体
    auto * physical_world = new G4PVPlacement(0,
                                              G4ThreeVector(0,0,0),
                                              logic_world,
                                              "world",
                                              0,
                                              false,
                                              0,
                                              checkOverlaps);
    // 将磁场配置到world
    logic_world->SetFieldManager(fieldManager,true);
 
    /***********************CsI探测器**********************************/
    // 创建csi探测器几何体
    auto * solid_csi = new G4Box("csi",        
                                    0.5*cm,      
                                    0.5*cm,   
                                    1*cm);   
    // 创建csi探测器逻辑体
    auto * logic_csi = new G4LogicalVolume(solid_csi,     // 待填充的几何体
                                           nistManager->FindOrBuildMaterial("G4_CESIUM_IODIDE"),         // 填充材料
                                           "csi");        // 逻辑体名

    // 配置csi探测器外观
    auto * visAttributs_csi = new G4VisAttributes(G4Color::White());   // 颜色为白色
    visAttributs_csi->SetVisibility(true);                             // 打开外观显示
    visAttributs_csi->SetForceSolid(true);                             // 外观设置为实心全填充
    logic_csi->SetVisAttributes(visAttributs_csi);                     // 外观信息配置到logic_wine

    // 创建csi探测器物理体
    G4RotationMatrix* rotationMatrix = new G4RotationMatrix();      // 定义一个旋转矩阵
    rotationMatrix->rotateX(90*deg);                                // 绕x轴旋转90°
    auto * physical_csi = new G4PVPlacement(rotationMatrix,                 // 旋转
                                             G4ThreeVector(0,6*cm,0),       // 摆放位置
                                             logic_csi,                     // 待摆放的逻辑体
                                             "csi",                         // 物理实体名
                                             logic_world,                   // 母体
                                             false,                         // 不镜像
                                             2,                             // 物理实体编号
                                             checkOverlaps);                // 打开边界冲突检查

    // 设置敏感体积
    fScoringVolume = logic_csi;        // 将敏感体积设置为logic_csi

    // 返回世界
    return physical_world;              // 将整个world交给runmanager

}

// 用于其他类获取设置的敏感体积的成员函数
G4LogicalVolume* G4ImproveDetectorConstruction::GetScoringVolume() const{

    // 返回逻辑体
    return fScoringVolume;
}

// 将逻辑体设置为Sensitive Detector
void G4ImproveDetectorConstruction::ConstructSDandField(){
    auto impSD = new G4ImproveSD("/TrackerChamberSD","TrackerHitsCollection");

    G4SDManager* sdManager = G4SDManager::GetSDMpointer();

    sdManager->AddNewDetector(impSD);

    SetSensitiveDetector("csi",impSD,true);
}